unit actionpatternselection;

{$mode objfpc}{$H+}
{$modeswitch nestedprocvars}


interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Spin,
  EditBtn, ButtonPanel, database;

type

  { TActionPatternSelectionForm }

  TActionPatternSelectionForm = class(TForm)
    AlwaysRadioButton: TRadioButton;
    ConditionGroupBox: TGroupBox;
    HpFromLabel: TLabel;
    HpFromSpinEdit: TSpinEdit;
    HpRadioButton: TRadioButton;
    HpToLabel: TLabel;
    HpToSpinEdit: TSpinEdit;
    MpFromLabel: TLabel;
    MpFromSpinEdit: TSpinEdit;
    MpRadioButton: TRadioButton;
    MpToLabel: TLabel;
    MpToSpinEdit: TSpinEdit;
    PartyLevelOrHigherLabel: TLabel;
    PartyLevelRadioButton: TRadioButton;
    PartyLevelSpinEdit: TSpinEdit;
    RatingGroupBox: TGroupBox;
    RatingSpinEdit: TSpinEdit;
    ResultButtonPanel: TButtonPanel;
    ContentScrollBox: TScrollBox;
    SkillComboBox: TComboBox;
    SkillGroupBox: TGroupBox;
    StateComboBox: TComboBox;
    StateRadioButton: TRadioButton;
    SwitchEditButton: TEditButton;
    SwitchRadioButton: TRadioButton;
    TurnNumberConstSpinEdit: TSpinEdit;
    TurnNumberMultiplierSpinEdit: TSpinEdit;
    TurnNumberPlusLabel: TLabel;
    TurnNumberRadioButton: TRadioButton;
    TurnNumberTimesXLabel: TLabel;
    procedure AlwaysRadioButtonChange(Sender: TObject);
    procedure FormHide(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure HpRadioButtonChange(Sender: TObject);
    procedure MpRadioButtonChange(Sender: TObject);
    procedure PartyLevelRadioButtonChange(Sender: TObject);
    procedure PercentParamSpinEditChange(Sender: TObject);
    procedure RatingSpinEditChange(Sender: TObject);
    procedure SkillComboBoxChange(Sender: TObject);
    procedure StateComboBoxChange(Sender: TObject);
    procedure StateRadioButtonChange(Sender: TObject);
    procedure SwitchEditButtonClick(Sender: TObject);
    procedure SwitchRadioButtonChange(Sender: TObject);
    procedure ParamSpinEditChange(Sender: TObject);
    procedure TurnNumberRadioButtonChange(Sender: TObject);
  private
    Db: TDatabase;
    procedure UnifyRadioButtonSizes;
  public
    SelectedSkillId: Integer;
    SelectedRating: Integer;
    SelectedCondType: Integer;
    SelectedCondParam1, SelectedCondParam2: Double;
    SelectedSwitch: Integer;
    function ShowSelection(SkillId, Rating, CondType: Integer; Param1, Param2: Double; ADb: TDatabase): Boolean;
  end;

  TRadioButtonCallback = procedure(Radio: TRadioButton) is nested;

var
  ActionPatternSelectionForm: TActionPatternSelectionForm;

implementation

uses
  Math, comboboxhelper, constants, namedindexselection;

{$R *.lfm}

{ TActionPatternSelectionForm }

procedure TActionPatternSelectionForm.SwitchEditButtonClick(Sender: TObject);
begin
  SelectedSwitch := NamedIndexSelectionForm.SelectSwitch(SelectedSwitch, Db);
  SelectedCondParam1 := SelectedSwitch;
  SwitchEditButton.Text := Db.GetSwitchName(SelectedSwitch);
end;

procedure TActionPatternSelectionForm.SwitchRadioButtonChange(Sender: TObject);
begin
  SwitchEditButton.Enabled := SwitchRadioButton.Checked;
  if SwitchRadioButton.Checked then begin
    SelectedCondType := ENEMY_ACTION_CONDITION_SWITCH;
    SelectedCondParam1 := SelectedSwitch;
    SelectedCondParam2 := 0;
  end;
end;

procedure TActionPatternSelectionForm.ParamSpinEditChange(
  Sender: TObject);
var
  SpinEdit: TSpinEdit;
begin
  SpinEdit := Sender as TSpinEdit;

  if SpinEdit.Tag = 1 then
    SelectedCondParam1 := SpinEdit.Value
  else if SpinEdit.Tag = 2 then
    SelectedCondParam2 := SpinEdit.Value
end;

procedure TActionPatternSelectionForm.TurnNumberRadioButtonChange(
  Sender: TObject);
begin
  TurnNumberConstSpinEdit.Enabled := TurnNumberRadioButton.Checked;
  if TurnNumberRadioButton.Checked then begin
    SelectedCondType := ENEMY_ACTION_CONDITION_TURN;
    TurnNumberMultiplierSpinEdit.Enabled := TurnNumberRadioButton.Checked;
    SelectedCondParam1 := TurnNumberConstSpinEdit.Value;
    SelectedCondParam2 := TurnNumberMultiplierSpinEdit.Value;
  end;
end;

procedure TActionPatternSelectionForm.FormHide(Sender: TObject);
begin
  SkillComboBox.Items.Clear;
  StateComboBox.Items.Clear;
end;

procedure TActionPatternSelectionForm.AlwaysRadioButtonChange(Sender: TObject);
begin
  if AlwaysRadioButton.Checked then begin
    SelectedCondType := ENEMY_ACTION_CONDITION_ALWAYS;
    SelectedCondParam1 := 0;
    SelectedCondParam2 := 0;
  end;
end;

procedure TActionPatternSelectionForm.UnifyRadioButtonSizes;
var
  MaxWidth: Integer = 0;

  procedure IterateOverRadioButtons(Callback: TRadioButtonCallback);
  begin
    { I did this because 'typed constants of classes or interfaces are not
     allowed', so I couldn't just declare an array of radiobuttons. Better
     solutions are welcome. }
    Callback(TurnNumberRadioButton);
    Callback(HpRadioButton);
    Callback(MpRadioButton);
    Callback(StateRadioButton);
    Callback(PartyLevelRadioButton);
    Callback(SwitchRadioButton);
  end;

  procedure SetAutoSizeOn(Radio: TRadioButton);
  begin
    Radio.AutoSize := True;
  end;

  procedure FindMaxWidth(Radio: TRadioButton);
  begin
   MaxWidth := Max(Radio.Width, MaxWidth);
  end;

  procedure SetMaxWidth(Radio: TRadioButton);
  begin
    Radio.AutoSize := False;
    Radio.Width := MaxWidth;
  end;

var
  NeedsFlipping: Boolean;
begin
  { Not sure why, but autosize magic only works with LTR, at least in Windows,
    so flip everything and then flip back if we're in RTL mode }
  NeedsFlipping := IsFlipped;
  if IsFlipped then
    FlipChildren(True);

  MaxWidth := 0;
  IterateOverRadioButtons(@SetAutoSizeOn);
  IterateOverRadioButtons(@FindMaxWidth);
  IterateOverRadioButtons(@SetMaxWidth);

  if NeedsFlipping then
    FlipChildren(True);
end;

function TActionPatternSelectionForm.ShowSelection(SkillId, Rating,
  CondType: Integer; Param1, Param2: Double; ADb: TDatabase): Boolean;
begin
  Db := ADb;
  SelectedSkillId := SkillId;
  SelectedRating := Rating;
  SelectedCondType := CondType;
  SelectedCondParam1 := Param1;
  SelectedCondParam2 := Param2;

  FillSkillComboBox(SkillComboBox, Db);
  FillStateComboBox(StateComboBox, Db);
  SkillComboBox.ItemIndex := SkillId - 1;
  RatingSpinEdit.Value := Rating;

  case CondType of
    ENEMY_ACTION_CONDITION_ALWAYS:
      AlwaysRadioButton.Checked := True;
    ENEMY_ACTION_CONDITION_TURN: begin
        TurnNumberRadioButton.Checked := True;
        TurnNumberConstSpinEdit.Value := Round(Param1);
        TurnNumberMultiplierSpinEdit.Value := Round(Param2);
      end;
    ENEMY_ACTION_CONDITION_HP: begin
        HpRadioButton.Checked := True;
        HpFromSpinEdit.Value := Round(Param1 * 100);
        HpToSpinEdit.Value := Round(Param2 * 100);
      end;
    ENEMY_ACTION_CONDITION_MP: begin
        MpRadioButton.Checked := True;
        MpFromSpinEdit.Value := Round(Param1 * 100);
        MpToSpinEdit.Value := Round(Param2 * 100);
      end;
    ENEMY_ACTION_CONDITION_STATE: begin
        StateRadioButton.Checked := True;
        StateComboBox.ItemIndex := Round(Param1 - 1);
      end;
    ENEMY_ACTION_CONDITION_PARTY_LV: begin
        PartyLevelRadioButton.Checked := True;
        PartyLevelSpinEdit.Value := Round(Param1);
      end;
    ENEMY_ACTION_CONDITION_SWITCH: begin
        SwitchRadioButton.Checked := True;
        SelectedSwitch := Round(Param1);
      end;
  end;

  if SelectedSwitch < 1 then
    SelectedSwitch := 1;
  SwitchEditButton.Text := Db.GetSwitchName(SelectedSwitch);

  ShowModal;

  ShowSelection := ModalResult = mrOK;
end;

procedure TActionPatternSelectionForm.FormShow(Sender: TObject);
begin
  UnifyRadioButtonSizes;
end;

procedure TActionPatternSelectionForm.HpRadioButtonChange(Sender: TObject);
begin
  HpFromSpinEdit.Enabled := HpRadioButton.Checked;
  if HpRadioButton.Checked then begin
    SelectedCondType := ENEMY_ACTION_CONDITION_HP;
    HpToSpinEdit.Enabled := HpRadioButton.Checked;
    SelectedCondParam1 := HpFromSpinEdit.Value / 100;
    SelectedCondParam2 := HpToSpinEdit.Value / 100;
  end;
end;

procedure TActionPatternSelectionForm.MpRadioButtonChange(Sender: TObject);
begin
  MpFromSpinEdit.Enabled := MpRadioButton.Checked;
  if MpRadioButton.Checked then begin
    SelectedCondType := ENEMY_ACTION_CONDITION_MP;
    MpToSpinEdit.Enabled := MpRadioButton.Checked;
    SelectedCondParam1 := MpFromSpinEdit.Value / 100;
    SelectedCondParam2 := MpToSpinEdit.Value / 100;
  end;
end;

procedure TActionPatternSelectionForm.PartyLevelRadioButtonChange(
  Sender: TObject);
begin
  PartyLevelSpinEdit.Enabled := PartyLevelRadioButton.Checked;
  if PartyLevelRadioButton.Checked then begin
    SelectedCondType := ENEMY_ACTION_CONDITION_PARTY_LV;
    SelectedCondParam1 := PartyLevelSpinEdit.Value;
    SelectedCondParam2 := 0;
  end;
end;

procedure TActionPatternSelectionForm.PercentParamSpinEditChange(Sender: TObject
  );
var
  SpinEdit: TSpinEdit;
begin
  SpinEdit := Sender as TSpinEdit;

  if SpinEdit.Tag = 1 then
    SelectedCondParam1 := SpinEdit.Value / 100
  else if SpinEdit.Tag = 2 then
    SelectedCondParam2 := SpinEdit.Value / 100
end;

procedure TActionPatternSelectionForm.RatingSpinEditChange(Sender: TObject);
begin
  SelectedRating := RatingSpinEdit.Value;
end;

procedure TActionPatternSelectionForm.SkillComboBoxChange(Sender: TObject);
begin
  SelectedSkillId := SkillComboBox.ItemIndex + 1;
end;

procedure TActionPatternSelectionForm.StateComboBoxChange(Sender: TObject);
begin
  SelectedCondParam1 := StateComboBox.ItemIndex + 1;
end;

procedure TActionPatternSelectionForm.StateRadioButtonChange(Sender: TObject);
begin
  StateComboBox.Enabled := StateRadioButton.Checked;
  if StateRadioButton.Checked then begin
    SelectedCondType := ENEMY_ACTION_CONDITION_STATE;
    SelectedCondParam1 := StateComboBox.ItemIndex + 1;
    SelectedCondParam2 := 0;
  end;
end;

end.

